home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 19
/
Aminet 19 (1997)(GTI - Schatztruhe)[!][Jun 1997].iso
/
Aminet
/
comm
/
tcp
/
Crak.lha
/
craksort2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-02-28
|
12KB
|
487 lines
/*
VERSION: 0.01 by Sudog Feb '97
So what if I have a non-standard version?
*/
#include <stdio.h>
#include <string.h>
#ifdef AMIGA
#include <dos/dos.h>
#include <exec/memory.h>
#endif
/* duh */
#define TRUE 1 /* generic true/false because I don't want to waste time */
#define FALSE 0 /* including exec/types.h so there. */
/* the following for passwd structure traversal */
#define USER 1 /* at user field in line */
#define PASSWD 2 /* at passwd field in passwd entry */
#define SAVE 3 /* after storing user & password, save it */
#define DONE 4 /* and after saving it for later, skip over rest */
/* maximum values for internal passwd structure */
#define NAMESIZE 15 /* for struct passwd and for parsepass routine */
#define SALTSIZE 3
#define PASSWDSIZE 14
#define WORDSIZE 20 /* maximum size of password in command line or password in dictfile */
/* values for return() from getnextdict */
#define DICT_DONE 1 /* dictionary has been exhausted */
#define DICT_ERROR 2 /* dictionary file is corrupt or something else just as fucked up */
#define SEPARATOR ':' /* passwd field separator.. : for unix, | for AmiTCP */
/*
** This is merely a small affectation because I am sometimes curious
** to have regular status updates.. uncomment this #define if you like
** something happening everytime the dictionary file has been entirely
** searched through..
*/
#define ANIMSIZE 4
#ifdef AMIGA
int CXBRK(void) {return(0);} /* sorry user we're gonna make SURE that you can't */
int chkabort(void) {return(0);} /* mess us up without giving us chance to clean up */
#endif
struct passwd
{
char name[NAMESIZE];
char salt[SALTSIZE];
char password[PASSWDSIZE];
struct passwd *nextitem;
struct passwd *lastitem;
short cracked;
};
FILE *dictionary; /* global because we want getnextdict() to have an open-and-ready */
/* file handle from which to read words from the dictionary when in */
/* dictionary mode */
char *crypt(char *, char *);
struct passwd *parsepass(char *);
void cleanup(struct passwd *);
void log(char *, char *, char *);
long getnextdict(char *, char *);
int main(int argc, char *argv[])
{
unsigned int counter;
unsigned int c=FALSE;
unsigned char commandword[WORDSIZE];
struct passwd *firstitem=NULL;
struct passwd *currentitem=NULL;
long status; /* for returns from various functions.. scratchpad */
#ifdef ANIMSIZE
char anim[] = "\\|/-";
int animcounter = 0;
#endif
#ifdef AMIGA
long actualsigs;
long waitmask = SIGBREAKF_CTRL_C;
#endif
dictionary=NULL; /* i don't want to do this more than once */
/* do some command line argument parsing */
/* this is hereby hard-coded.*/
for (counter = 0; counter < argc; counter++)
{
if (argv[counter][0] == '-')
{
/*
** The following accepts the - as an indicator, and then it copies the
** rest of this particular argument as a word to search a passwd file for.
** The reason this isn't hard-coded as argv[2] is for future expandability--
** sort of a functional work-in-progress.
*/
c = TRUE;
for (counter=1; counter < WORDSIZE; counter++)
{
commandword[counter-1] = argv[2][counter];
if (commandword[counter-1] == 0) break;
}
break;
}
if (argv[counter][0] == '?')
{
/*
** I could never really see the harm in goto statements within programs.
** "A Book On C" says that goto statements are bad programming pratice.
** Whatever..
*/
usage:
printf("Usage: %s <passwdfile> -<word> [outputfile]\n", argv[0]);
printf(" %s <passwdfile> <dictfile> [outputfile]\n", argv[0]);
printf(" %s ?\n", argv[0]);
printf("This program written in Feb, '97 by sudog.\n");
printf("So there.\n");
exit(0);
}
}
counter = 0;
if (argc > 2)
{
if (firstitem = parsepass(argv[1]))
{
currentitem = firstitem;
/*
** This section deals with a command-line supplied password.
*/
if (c)
{
while (currentitem != NULL)
{
if (!strcmp(currentitem->password, crypt(commandword, currentitem->salt)))
{
printf("%s %s\n", currentitem->name, commandword);
if (argc > 3)
{
log(argv[3], currentitem->name, commandword);
}
}
/* This section is amiga-only--it allows the user to break the program,
** CLEANLY! (Ie: We trap SIGBREAKF_CTRL_C and clean up the memory we allocated.)
*/
#ifdef AMIGA
actualsigs = CheckSignal(waitmask);
if (actualsigs)
{
cleanup(firstitem);
}
#endif
currentitem = currentitem->nextitem;
}
}
/*
** This section deals with a dictionary file!
** TODO:
** Add place holder so a system crash can be survived and iterations can
** continue from last point... VERY cool. let's do som background cracking!
*/
/*
** First priority is to check the entire dictionary against the
** current passwd entry. It's MUCH MUCH INCREDIBLY FASTER then.
*/
else
{
currentitem=firstitem;
/*
** A simple while loop to search an entire dictionary on a single
** password entry. Trust me, this saves a SHITLOAD of time, since
** for each new salt which is used, crypt() has to re-set all its
** damned data structure and shit. VERY crappy. Otherwise it zips
** through things in like, 500 keys per second. At least, on my
** machine, compared with maybe 10 keys/sec otherwise.
*/
while ( currentitem != NULL )
{
while (((status=getnextdict(commandword, argv[2])) != DICT_DONE) && (status != DICT_ERROR))
{
if (!currentitem->cracked)
{
if (!strcmp(currentitem->password, crypt(commandword, currentitem->salt)))
{
printf("%s %s\n", currentitem->name, commandword);
currentitem->cracked = TRUE;
if (argc > 3)
{
log(argv[3], currentitem->name, commandword);
}
}
}
#ifdef AMIGA
actualsigs = CheckSignal(waitmask);
if (actualsigs)
{
cleanup(firstitem);
}
#endif
}
if (status == DICT_ERROR)
{
printf("Error: Unable to access dictionary file..\n");
break;
}
if (status == DICT_DONE)
{
#ifdef ANIMSIZE
printf("%c%c", anim[animcounter], 8);
animcounter++;
if (animcounter >= ANIMSIZE)
{
animcounter = 0;
}
#endif
}
currentitem=currentitem->nextitem;
}
}
}
else
{
printf("Error in parsing password file.\n");
}
}
else
{
printf("Error. You don't have a clue. Here. Have one.\n");
goto usage;
}
cleanup(firstitem);
}
/*
** In order that we get dictionary words, we have to
** return words in cyclical order. Ie: We have to
** get the first word after we got the last word.
** So we aren't returning any end-of-file conditions.
** We're just returning words unless an error
** condition exists.
*/
long getnextdict(char *commandword, char *filename)
{
long counter=0;
int gotone=FALSE;
char temp;
if (commandword == NULL && filename == NULL)
{
if (dictionary)
{
fclose(dictionary);
}
return(0);
}
if (!dictionary)
{
if (!(dictionary = fopen(filename, "r")))
{
return(DICT_ERROR);
}
}
if (dictionary)
{
while ( 1 )
{
temp = fgetc(dictionary);
if (feof(dictionary))
{
if (gotone)
{
commandword[counter] = 0;
return(0);
}
else
{
/*
** We're going to re-use the dictionary file again and again and
** again until we're TOLD to close it with getnextdict(NULL, NULL);
*/
rewind(dictionary);
return(DICT_DONE);
}
}
else if (temp > 31 && temp < 127)
{
if (gotone == FALSE)
{
gotone = TRUE;
}
if (counter < WORDSIZE)
{
commandword[counter++] = temp;
}
}
else
{
if (gotone == TRUE)
{
commandword[counter] = 0;
return(0);
}
}
} /* end of while loop */
}
}
/*
** Excellently enough, calloc() remembers how big the memory chunks
** it allocated are, so a call to free() doesn't have to specify anything
** but the pointer!! ANSI-C rules!
*/
void cleanup(struct passwd *firstitem)
{
struct passwd *currentitem;
while (firstitem != NULL)
{
currentitem = firstitem->nextitem;
free(firstitem);
firstitem = currentitem;
}
getnextdict(NULL, NULL);
exit(0);
}
void log (char *filename, char *username, char *password)
{
FILE *output;
if (output = fopen(filename, "a"))
{
fprintf(output, "%s %s\n", username, password);
fclose(output);
}
else
{
printf("Error: Unable to open output file!\n");
}
}
/*
** This routine opens a passwd file, and parses it according to the
** following rules:
**
** {user}{separator}{passwd field entry}{separator}
** There MUST be two separators per line.. the separator should be defined as
** SEPARATOR in the preprocessor.. usually ':' for UNIX-style passwd files.
*/
/*
** We use a state variable to define which part of the passwd entry we
** are currently processing.. it's more used as a sort of directive..
** if it's USER, store it in the user field of the struct passwd..
** etc etc..
*/
struct passwd *parsepass(char *filename)
{
struct passwd *currentitem=NULL;
struct passwd *firstitem=NULL;
struct passwd *floatitem=NULL;
unsigned int counter = 0;
unsigned int state; /* the part of the field we're parsing right now */
unsigned int ff = FALSE;
FILE *input;
char temp;
if (input = fopen(filename, "r"))
{
while ( 1 )
{
temp = fgetc(input);
if (feof(input)) break;
if (temp > 31 && temp < 127)
{
/*
** ff here is being used as a sort of flip-flop switch. It is used for
** QUICKLY skipping over non-printable characters.
*/
if (ff == FALSE)
{
ff = TRUE;
if (!(floatitem = (struct passwd *)calloc(1, sizeof(struct passwd))))
{
printf("Error: Unable to allocate %d bytes. Exiting..\n", sizeof(struct passwd));
cleanup(firstitem);
}
state = USER;
}
if (state == USER)
{
if (temp != SEPARATOR && counter < NAMESIZE)
{
floatitem->name[counter++] = temp;
}
if (temp == SEPARATOR)
{
state = PASSWD;
counter = 0;
}
}
else if (state == PASSWD)
{
if (temp != SEPARATOR && counter < PASSWDSIZE)
{
if (counter < 2)
{
floatitem->salt[counter] = temp;
}
floatitem->password[counter++] = temp;
}
if (temp == SEPARATOR)
{
state = SAVE;
counter = 0;
}
}
if (state == SAVE)
{
if (!firstitem)
{
firstitem=floatitem;
}
else
{
currentitem=firstitem;
/*
** We are using a doubly-linked list to store our list of passwd
** entries.. doubly-linked lists are cool! buhuhuhuhuhuhuhuhuh hehe
*/
while ( 1 )
{
if ((strcmp(floatitem->salt, currentitem->salt)) <= 0)
{
floatitem->nextitem=currentitem;
floatitem->lastitem=currentitem->lastitem;
currentitem->lastitem = floatitem;
if (floatitem->lastitem != NULL)
{
floatitem->lastitem->nextitem = floatitem;
}
else
{
firstitem = floatitem;
}
break;
}
if (currentitem->nextitem == NULL)
{
currentitem->nextitem = floatitem;
floatitem->lastitem = currentitem;
break;
}
currentitem=currentitem->nextitem;
}
}
state = DONE;
}
}
else
{
state = USER;
ff = FALSE;
}
}
fclose(input);
}
else
{
printf("Error: Unable to open specified passwd file.\n");
}
return(firstitem);
}